/*
	本模块：
				1.检测被测信号的频率
				2.采用等精度测量法，检测频率
				
*/


module frequency_test(

	input		wire 				clk					,				//50M系统时钟信号
	input		wire 				ret_n					,				//复位信号
	input		wire 				test_clk				,				//被检测频率的时钟信号
	input		wire				standard_clk,				//标准测量时钟
	
	output	reg	[29:0]	frequency_number					//检测到的频率数据输出

);
	
	/*
		以下：对参数的定义
	*/
	parameter 	stable_max 			= 24'd12_500_000,			//波形稳定状态
					data_gather_max	= 28'd62_500_000,			//频率检测状态
					data_count_max		= 28'd75_000_000;			//数据处理状态
	
	parameter 	standard_test_clk = 28'd200_000_000;			//标准频率最大值
					
	
	

	/*
		以下：对变量进行定义
	*/
	reg	[1:0]		register;					//定义两个寄存器对被测信号进行寄存
	reg				test_en;						//频率检测模块的使能信号
	reg	[27:0]	cnt_software_door;		//软件闸门计数器
	reg				software_door_en;			//软件闸门
	reg	[29:0]	cnt_frequency_test;		//被测频率计数器
	reg				gage_x;						//实际阀门
	reg				gage_x_delay;				//实际阀门延时一拍
	
	reg	[29:0]	cnt_standard;				//标准测量时钟计数器
	reg				gage_s;						//标准阀门
	reg				gage_s_delay;				//标准阀门延时一拍
	
	reg	[29:0]	gage_x_data;				//对被检测计数器值进行提取缓存
	reg	[29:0]	gage_s_data;				//对标准测量时钟计数器值进行提取缓存
	
	reg	[63:0]	frequency_number_keep;	//对数据处理缓存
	
	wire				nedge_x;						//实际阀门下降沿检测信号
	wire				nedge_s;						//标准阀门下降沿检测信号
	wire				test_judge;					//判断是否有被测信号
	
	/*
		以下：对变量进行赋值编写
	*/
	
	//对 register 寄存器进行编写
	always @(posedge clk or negedge ret_n)
		if(!ret_n)
			register <= 2'b0;
		else 
			begin 
				register[0] <=  test_clk;
				register[1]	<=	 register[0];
			end 
			
	//对 test_judge 被测信号的判断信号进行编写
	assign	test_judge = (!register[0] && register[1])?	1'b1 : 1'b0;
	
	//对 test_en 频率检测使能信号进行编写
	always @(posedge clk or negedge ret_n)
		if(!ret_n)
			test_en <= 1'b0;
		else if(test_judge == 1'b1)
			test_en <= 1'b1;
		else 
			test_en <= test_en;
	
	//对 cnt_software_door 软件阀门计计数器进行编写
	always @(posedge clk or negedge ret_n)
		if(!ret_n)
			cnt_software_door <=	28'd0;
		else if(cnt_software_door == data_count_max - 1'b1)
			cnt_software_door <=	28'd0;
		else if(test_en == 1'b1)
			cnt_software_door <= cnt_software_door + 1'b1;
		else 
			cnt_software_door <=	28'd0;
			
	//对 software_door_en 软件阀门使能信号进行编写
	always @(posedge clk or negedge ret_n)
		if(!ret_n)
			software_door_en <= 1'b0;
		else if(cnt_software_door == stable_max - 1'b1)
			software_door_en <= 1'b1;
		else if(cnt_software_door == data_gather_max - 1'b1)
			software_door_en <= 1'b0;
		else 
			software_door_en <= software_door_en;
			
	//对 gage_x 实际阀门信号进行编写
	always @(posedge test_clk or negedge ret_n)
		if(!ret_n)
			gage_x <= 1'b0;
		else if(software_door_en == 1'b1)
			gage_x <= 1'b1;
		else if(software_door_en == 1'b0)
			gage_x <= 1'b0;
		else 
			gage_x <= gage_x;
	
	
			
	//对 cnt_frequency_test 被测频率计数器进行编写
	always @(posedge test_clk or negedge ret_n)
		if(!ret_n)
			cnt_frequency_test <= 30'd0;
		else if(gage_x == 1'b1)
			cnt_frequency_test <= cnt_frequency_test + 1'b1;
		else
			cnt_frequency_test <= 30'd0;
		
	
	//对 gage_x_delay 实际阀门信号延时一拍进行编写
	always @(posedge test_clk or negedge ret_n)
		if(!ret_n)
			gage_x_delay <= 1'b0;
		else 
			gage_x_delay <= gage_x;
	
	//对 nedge_x 实际检测结束下降沿信号进行编写
	assign nedge_x = (gage_x_delay && !gage_x) ? 1'b1 : 1'b0;
	
	
	
	
	//对 gage_s 标准阀门信号进行编写
	always @(posedge standard_clk or negedge ret_n)
		if(!ret_n)
			gage_s <= 1'b0;
		else if(gage_x == 1'b1)
			gage_s <= 1'b1;
		else if(gage_x == 1'b0)
			gage_s <= 1'b0;
		else 
			gage_s <= gage_s;
	
	
	//对 cnt_standard 标准时钟计数器进行编写
	always @(posedge standard_clk or negedge ret_n)
		if(!ret_n)
			cnt_standard <= 30'd0;
		else if(gage_s == 1'b1)
			cnt_standard <= cnt_standard + 1'b1;
		else 
			cnt_standard <= 30'd0;
	
	//对 gage_s_delay 标准阀门信号进行寄存一拍进行编写
	always @(posedge standard_clk or negedge ret_n)
		if(!ret_n)
			gage_s_delay <= 1'b0;
		else 
			gage_s_delay <= gage_s;
			
	//对 nedge_s 标准阀门下降沿检测信号进行编写
	assign nedge_s = (gage_s_delay && !gage_s) ? 1'b1 : 1'b0;

	//对 gage_x_data 实际计数值提取数据进行编写
	always @(posedge test_clk or negedge ret_n)
		if(!ret_n)
			gage_x_data <= 30'd0;
		else if(nedge_x == 1'b1)
			gage_x_data <= cnt_frequency_test;
		else	
			gage_x_data <= gage_x_data;

	//对 gage_s_data 标准计算值提取数据进行编写
	always @(posedge standard_clk or negedge ret_n)
		if(!ret_n)
			gage_s_data <= 30'd0;
		else if(nedge_s == 1'b1)
			gage_s_data <= cnt_standard;
		else 
			gage_s_data <= gage_s_data;


	wire [31:0]yshang;
	//对 frequency_number_keep 数据处理缓存信号进行编写
	always @(posedge clk or negedge ret_n)
		if(!ret_n)
			frequency_number_keep <= 64'd0;
		else if(test_en == 1'b1 && cnt_software_door == data_count_max - 1'b1)
			frequency_number_keep <= standard_test_clk*yshang;//(standard_test_clk * gage_x_data/ gage_s_data
		else if(test_en == 1'b1)
			frequency_number_keep <= frequency_number_keep;
		else 
			frequency_number_keep <= 64'd0;
			
	//硬件除法模块
	drive_division  drive_division_1(  
		.	clk			(standard_clk),
		.	en			(1'b1),
		.	dividend	({2'd0,gage_x_data}), //被除数  
		.	divisor		({2'd0,gage_s_data}),  //除数
					
		.	yshang		(yshang),//商数  
		.	yyushu 		() //余数
	);
	
	
	//对 frequency_number 输出数据进行编写
	always @(posedge clk or negedge ret_n)
		if(!ret_n)
			frequency_number <= 30'd0;
		else if(test_en == 1'b1)
			frequency_number <= frequency_number_keep[29:0];
		else 
			frequency_number <= 30'd0;


endmodule 




























